package apis

import (
	"errors"
	"fmt"
	"strconv"
	"syscall"

	"gitee.com/sansaniot/ssiot-core/httpmvc/api"
	"gitee.com/sansaniot/ssiot-core/httpmvc/jwtauth/user"
	"gitee.com/sansaniot/ssiot-core/serrors"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/shirou/gopsutil/net"
	"gorm.io/gorm"

	"ssadmin/common/constant"
	"ssadmin/common/utils"
	"ssadmin/internal/admin/models"
	"ssadmin/internal/admin/models/command"
	"ssadmin/internal/admin/models/query"
	"ssadmin/internal/admin/service"
)

type Sys struct {
	api.Api
}

func (e Sys) GetGoto(c *gin.Context) {
	userModel := models.User{}

	err := e.MakeContext(c).
		MakeModel(&userModel.Model).
		Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	userId := user.Get(c, constant.CacheKeyUserId).(string)
	creatorId := user.Get(c, constant.CacheKeyCreatorId).(string)

	if creatorId != "1" {
		userId = creatorId
		return
	}

	userModel.UserId = userId
	_ = userModel.Orm.First(&userModel).Error
	e.Data(userModel.Goto)
}

// SaveGoto 保存
func (e Sys) SaveGoto(c *gin.Context) {
	req := command.SysGotoReq{}
	userModel := models.User{}

	err := e.MakeContext(c).
		Bind(&req).
		MakeModel(&userModel.Model).
		Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	userId := user.Get(c, constant.CacheKeyUserId).(string)
	creatorId := user.Get(c, constant.CacheKeyCreatorId).(string)

	if creatorId != "1" {
		e.Fail(0, "只有租户可以修改系统信息")
		return
	}

	updates := map[string]interface{}{
		"id":   userId,
		"goto": req.Goto,
	}

	userModel.UserId = userId
	err = userModel.Orm.Model(&userModel).Updates(updates).Error
	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	e.Ok(nil)
}

func (e Sys) PortDetect(c *gin.Context) {
	req := query.DevNetstatReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	connectionStats, _ := net.Connections("all")
	result := make([]map[string]interface{}, 0)
	for _, v := range connectionStats {
		localPort := int(v.Laddr.Port)
		if localPort != req.Port {
			continue
		}
		remotePortStr := strconv.Itoa(int(v.Raddr.Port))
		socketType := utils.If(v.Type == syscall.SOCK_STREAM, "tcp", "udp").(string)
		fourSix := utils.If(v.Family == syscall.AF_INET, "", "6").(string)
		result = append(result, map[string]interface{}{
			"type":       socketType + fourSix,
			"fd":         v.Fd,
			"localAddr":  v.Laddr.IP + ":" + strconv.Itoa(localPort),
			"remoteAddr": v.Raddr.IP + ":" + utils.If(remotePortStr == "0", "*", remotePortStr).(string),
			"status":     v.Status,
		})
	}
	e.Data(result)
}

func (e Sys) GetDataKeep(c *gin.Context) {
	// 请求参数
	req := query.SysDataKeepQuery{}
	// 模型
	m := &models.SysDataKeep{}
	// 上下文
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeModel(&m.Model).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	// 用户信息
	req.LoadUser(c)
	var result interface{}
	// 执行
	if err = m.GetByAgencyId(req.UserInfo.AgencyId); err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			e.Logger.Error(err)
			e.Fail(0, err.Error())
			return
		}
	}
	if m.Keep > 0 {
		result = m.Keep
	}
	// 返回
	e.Ok(map[string]interface{}{
		"default": constant.DefaultDataKeepDays,
		"keep":    result,
	})
}

func (e Sys) SaveDataKeep(c *gin.Context) {
	// 请求参数
	req := command.DataKeepReq{}
	// 业务service
	s := &service.DataDetail{}
	// 模型
	m := &models.SysDataKeep{}
	// 上下文
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req, binding.JSON).
		MakeModel(&m.Model).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	if req.Keep > constant.DefaultDataKeepDays {
		e.Fail(0, fmt.Sprintf("数据限制存储%v天", constant.DefaultDataKeepDays))
		return
	}
	// service注入实体
	s.SetDataKeepModel(m)
	// 用户信息
	req.LoadUser(c)
	// 执行
	if err = s.SaveDataKeep(&req); err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	// 返回
	e.Ok(nil)
}

func (e Sys) GetFileClean(c *gin.Context) {
	// 请求参数
	req := query.SysConfQuery{}
	// 模型
	m := &models.SysConf{}
	// 上下文
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeModel(&m.Model).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	// 用户信息
	req.LoadUser(c)
	var result []models.SysConf
	// 执行
	if result, err = m.GetByKeyList([]string{constant.FileCleanThreshold, constant.FileCleanType}); err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	if len(result) == 0 {
		result = append(result, models.SysConf{
			Key:    constant.FileCleanThreshold,
			Value:  "10",
			Remark: "磁盘余量百分比，触发业务文件清理",
		})
		result = append(result, models.SysConf{
			Key:    constant.FileCleanType,
			Value:  "roll",
			Remark: "文件清理方式,roll:滚动,discard:丢弃",
		})
	}
	// 返回
	e.Ok(result)
}

func (e Sys) SaveFileClean(c *gin.Context) {
	// 请求参数
	req := command.FileCleanReq{}
	// 业务service
	s := &service.DataDetail{}
	// 模型
	m := &models.SysConf{}
	// 上下文
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req, binding.JSON).
		MakeModel(&m.Model).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	// service注入实体
	s.SetSysConfModel(m)
	// 用户信息
	req.LoadUser(c)
	if req.UserId != "1" {
		e.Fail(0, "admin可操作")
		return
	}
	// 执行
	if err = s.SaveFileClean(&req); err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	// 返回
	e.Ok(nil)
}

func (e Sys) SysDataSync(c *gin.Context) {
	// 请求参数
	req := command.TableSync{}
	// 业务service
	s := &service.DataDetail{}
	// 上下文
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req, binding.JSON).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	// 用户信息
	req.LoadUser(c)
	// 执行
	var result interface{}
	if result, err = s.SysDataSync(&req); err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}
	// 返回
	e.Data(result)
}
